package com.sms.util;

import com.sms.exception.DataFileCorruptedException;

import com.sms.model.Course;
import com.sms.model.Score;
import com.sms.model.Student;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;



/**
 * 文件操作工具类
 * 位置：com.sms.util.FileUtil
 */
public final class FileUtil {
    /**
     * 从文件读取所有行
     *
     * @param filename 文件名（相对data目录路径）
     * @return 行内容列表
     * @throws IOException 当文件不存在或读取失败时抛出
     */
    public static List<String> readLines(String filename) throws IOException {
        if (!fileExists(filename)) {
            throw new IOException("文件不存在: " + filename);
        }
        return Files.readAllLines(Path.of(filename));
    }

    /**
     * 写入数据到文件
     *
     * @param filename 文件名
     * @param lines    要写入的行内容
     * @throws IOException 当写入失败时抛出
     */
    public static void writeLines(String filename, List<String> lines) throws IOException {
        createFileIfNotExists(filename);
        Files.write(Path.of(filename), lines, StandardCharsets.UTF_8);
    }

    /**
     * 写入数据到文件（追加模式）
     *
     * @param filename 文件名
     * @param lines    要写入的行内容
     * @param append   是否追加模式
     * @throws IOException 当写入失败时抛出
     */
    public static void writeLines(String filename, List<String> lines, boolean append) throws IOException {
        createFileIfNotExists(filename);
        Files.write(Path.of(filename), lines, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
    }

    /**
     * 检查文件是否存在
     *
     * @param filename 文件名
     * @return true-存在, false-不存在
     */
    public static boolean fileExists(String filename) {
        return Files.exists(Path.of(filename));
    }

    /**
     * 如果文件不存在则创建
     *
     * @param filename 文件名
     * @throws IOException 当创建失败时抛出
     */
    public static void createFileIfNotExists(String filename) throws IOException {
        if (!fileExists(filename)) {
            System.out.println("当前工作目录: " + System.getProperty("user.dir"));
            Files.createFile(Path.of(filename));
        }
    }

    /**
     * 加载学生数据文件
     *
     * @param filename 文件名
     * @return 对象列表
     * @throws IOException                当文件读取失败时抛出
     * @throws DataFileCorruptedException 当数据格式错误时抛出
     */
    public static List<Student> loadStudents(String filename) throws IOException, DataFileCorruptedException {
        if (!fileExists(filename)) {
            throw new IOException("文件不存在: " + filename);
        }

        List<String> lines = readLines(filename);

        if (lines.isEmpty()) {
            throw new IOException("文件为空" + filename);
        }

        lines.remove(0);//删除表头id,name,age,gender,className

        List<Student> students = new ArrayList<>();

        for (String l : lines) {
            if (l == null || l.trim().isEmpty()) {
                continue;  // 跳过空行
            }

            String[] split = l.split(",");

            if (split.length < 5) {
                throw new DataFileCorruptedException("列数不足: " + l);
            }

            try {
                Student student = new Student();
                student.setId(split[0]);
                student.setName(split[1]);
                student.setAge(Integer.parseInt(split[2]));
                student.setGender(split[3]);
                student.setClassName(split[4]);

                students.add(student);
            } catch (NumberFormatException e) {
                throw new DataFileCorruptedException("年龄格式错误: " + split[1]);
            }
        }
        return students;
    }


    /**
     * 加载成绩数据文件
     *
     * @param filename 文件名
     * @return 对象列表
     * @throws IOException                当文件读取失败时抛出
     * @throws DataFileCorruptedException 当数据格式错误时抛出
     */
    public static List<Score> loadScores(String filename) throws IOException, DataFileCorruptedException {
        if (!fileExists(filename)) {
            throw new IOException("文件不存在: " + filename);
        }

        List<String> lines = readLines(filename);

        if (lines.isEmpty()) {
            throw new IOException("文件为空" + filename);
        }

        lines.remove(0);//删除表头id,name,age,gender,className

        List<Score> scores = new ArrayList<>();

        for (String l : lines) {
            if (l == null || l.trim().isEmpty()) {
                continue;  // 跳过空行
            }

            String[] split = l.split(",");

            if (split.length < 4) {
                throw new DataFileCorruptedException("列数不足: " + l);
            }

            try {
                Score score = new Score();
                score.setStudentId(split[0]);
                score.setCourseId(split[1]);
                score.setScore(Double.parseDouble(split[2]));
                score.setExamDate(split[3]);

                scores.add(score);
            } catch (NumberFormatException e) {
                throw new DataFileCorruptedException("成绩格式错误: " + split[1]);
            }
        }
        return scores;
    }



    /**
     * 加载课程数据文件
     *
     * @param filename 文件名
     * @return 对象列表
     * @throws IOException                当文件读取失败时抛出
     * @throws DataFileCorruptedException 当数据格式错误时抛出
     */
    public static List<Course> loadCourses(String filename) throws IOException, DataFileCorruptedException {
        if (!fileExists(filename)) {
            throw new IOException("文件不存在: " + filename);
        }

        List<String> lines = readLines(filename);

        if (lines.isEmpty()) {
            throw new IOException("文件为空" + filename);
        }

        lines.remove(0);//删除表头id,name,age,gender,className

        List<Course> courses = new ArrayList<>();

        for (String l : lines) {
            if (l == null || l.trim().isEmpty()) {
                continue;  // 跳过空行
            }

            String[] split = l.split(",");

            if (split.length < 3) {
                throw new DataFileCorruptedException("列数不足: " + l);
            }

            try {
                Course course = new Course();
                course.setCourseId(split[0]);
                course.setCourseName(split[1]);
                course.setCredit(Double.parseDouble(split[2]));

                courses.add(course);
            } catch (NumberFormatException e) {
                throw new DataFileCorruptedException("学分格式错误: " + split[2]);
            }
        }
        return courses;
    }





    /**
     * 保存学生数据到文件
     *
     * @param filename 文件名
     * @param students 学生列表
     * @throws IOException 当文件写入失败时抛出
     */
    public static void saveStudents(String filename, List<Student> students) throws IOException {
        createFileIfNotExists(filename);
        //id,name,age,gender,className
        List<String> lines = new ArrayList<>();
        lines.add("id,name,age,gender,className" + System.lineSeparator());
        for (Student s : students) {
            String sb = s.getId() +
                    "," +  // 字段分隔符！
                    s.getName() +
                    "," +
                    s.getAge() +
                    "," +
                    s.getGender() +
                    "," +
                    s.getClassName() +
                    System.lineSeparator();//换行符！
            lines.add(sb);
        }
        //覆盖模式
        writeLines(filename, lines);
    }

    /**
     * 保存学生数据到文件
     * @param filename
     * @param students
     * @param append
     * @throws IOException
     */
    public static void saveStudents(String filename, List<Student> students, boolean append) throws IOException {
        createFileIfNotExists(filename);
        //id,name,age,gender,className
        List<String> lines = new ArrayList<>();
        lines.add("id,name,age,gender,className" + System.lineSeparator());
        for (Student s : students) {
            String sb = s.getId() +
                    "," +  // 字段分隔符！
                    s.getName() +
                    "," +
                    s.getAge() +
                    "," +
                    s.getGender() +
                    "," +
                    s.getClassName() +
                    System.lineSeparator();//换行符！
            lines.add(sb);
        }
        //追加模式
        writeLines(filename, lines, true);
    }
}